import java.io.*;



import java.util.*;
import java.security.acl.LastOwnerException;
import java.text.*;
public class AnalyzeWithExistDir1 {

	static Properties dir_props= new Properties();

	static Properties edir_props= new Properties();
	static PrintWriter eout;
	static PrintWriter eoutrm;
	static List<String> edirs= new ArrayList<String>();
	static boolean generateScriptFlag=false;

	static String e="second";
	public static void main(String[] args) throws Exception{
		File f1=new File(e);
		if(f1.exists()&& !f1.isDirectory()){
			System.out.println("please delete \"second\" file");
			System.exit(0);
		}else 	if(!f1.exists()){
			f1.mkdirs();
		}else{
			Process pc=Runtime.getRuntime().exec(new String[]{"mv","second","second"+new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(new Date())});
			pc.waitFor();
			pc=Runtime.getRuntime().exec(new String[]{"mkdir","second"});
			pc.waitFor();
		}

		e+="/";
		AnalyzeAllFind.pardir=e;

		AnalyzeAllFind.main(args);
		
		TreeSet<String> allEDirs=new TreeSet<String>();
		TreeMap<String,String> delEDirs=new TreeMap<String,String>();
		ArrayList<String> needEDirs=new ArrayList<String>();
		ArrayList<String> noNeedEDirs=new ArrayList<String>();
		if((new File(args[0])).isFile())
			args[0]=args[0].replace("__", "/");

		
		edir_props= loadProperties(e+".dir.txt");
		dir_props=loadProperties(".dir.txt");
		
		Object[] earr=edir_props.values().toArray();
		for(Object ob:earr){
			allEDirs.add((String)ob);	
		}
		needEDirs.addAll(allEDirs);
		
		
		
		eout=new PrintWriter(e+"dirs1.log");
		eoutrm=new PrintWriter(e+"rm2_unsorted.sh");

		File _dir= new File("tmp");
		File e_dir= new File(e+"tmp");
		File[] farr=_dir.listFiles();
		File[] efarr=e_dir.listFiles();
		Long mx=Long.MAX_VALUE;
		TreeMap<Long,TreeSet<String>> fmap= new TreeMap<Long, TreeSet<String>>();
		TreeMap<Long,TreeSet<String>> efmap= new TreeMap<Long, TreeSet<String>>();
		TreeMap<Long,TreeSet<String>> combinedfmap= new TreeMap<Long, TreeSet<String>>();
		for(File _f:farr){
			String _name_=_f.getName();
			int _ii=_name_.lastIndexOf("_");
			int _jj=_name_.lastIndexOf(".");
			Long sz=mx-Long.parseLong(_name_.substring(_ii+1,_jj));
			TreeSet<String> strs= fmap.get(sz);
			if(strs==null)
				strs=new TreeSet<String>();
			strs.add(_f.getName());
			fmap.put(sz, strs);
		}
		
		for(File _f:efarr){
			String _name_=_f.getName();
			int _ii=_name_.lastIndexOf("_");
			int _jj=_name_.lastIndexOf(".");
			Long sz=mx-Long.parseLong(_name_.substring(_ii+1,_jj));
			TreeSet<String> strs= efmap.get(sz);
			if(strs==null)
				strs=new TreeSet<String>();
			strs.add(_f.getName());
			efmap.put(sz, strs);
		}
		
		Set<String> _del=new TreeSet<String>();
		Set<String> coveredDirs=new TreeSet<String>();
		Set<Long> keys=efmap.keySet();
		
		long gain=0;
		for(Long key:keys){
			if(fmap.get(key)!= null  && fmap.get(key).size()>0){
				TreeSet<String> vals=fmap.get(key);
				List<String> newvals=new ArrayList<String>();
				newvals.addAll(efmap.get(key));
				for(String val:vals){
					Long _sz=(999999999999999L-Long.parseLong(val.substring(0,15)));
					if(_sz==0)
						continue;
					String _head="=======SIZE="+_sz+"=====leng="+(mx-key)+"============";
					boolean _print_hd=false;
					
					String _val_path=path(val.substring(15));
					if(_val_path.startsWith(args[0]))
						continue;
					int __v=_val_path.lastIndexOf("/");
					for(int _i=0;_i<newvals.size();_i++){
						String newval=newvals.get(_i);
						String _new_val_path=epath(newval.substring(15));
						if(!_new_val_path.equals(_val_path)){
							int __n=_new_val_path.lastIndexOf("/");
							String _pn1=_new_val_path.substring(0,__n);
							String _pv1=_val_path.substring(0,__v);
							String _par2=_pv1+" "+_pn1;
							if(_del.contains(_pn1)){
								_del.add(_new_val_path);
							}
							if(coveredDirs.contains(_pv1)){
								coveredDirs.add(_val_path);
							}
							if(coveredDirs.contains(_pn1)){
								coveredDirs.add(_new_val_path);
							}
							if(coveredDirs.contains(_pn1) && coveredDirs.contains(_pv1)){
								continue;
							}
							
							if(dif.comp(new String[]{"tmp/"+val,e+"tmp/"+newval})){
									if(!_print_hd){
										_print_hd=true;
									}
									if(!coveredDirs.contains(_new_val_path) && !_del.contains(_val_path)){
										eout.println("meld \""+_val_path+"\" \""+_new_val_path+"\"");
										eout.flush();
										eoutrm.println("meld \""+_val_path+"\" \""+_new_val_path+"\"");
										eoutrm.println("rm -rI \""+_new_val_path+"\"");
										_del.add(_new_val_path);
										if(generateScriptFlag)
										for(int _p=0;_p<needEDirs.size();_p++){
											if((needEDirs.get(_p)+"/").startsWith(_new_val_path+"/")){
												needEDirs.remove(_p);
												_p--;
											}
										}
										if(generateScriptFlag)
											noNeedEDirs.add(_new_val_path);
										coveredDirs.add(_val_path);
										coveredDirs.add(_new_val_path);
										gain+=_sz;
									}
								
							}
							else{
							}
						}else{
						}
					}
					
					
				}
			}
		}
		eout.println("\ngain="+gain);
		eout.flush();
		
		ArrayList<String> cpFileListFile= new ArrayList<String>();

		if(generateScriptFlag){
			TreeSet<String> sts= new TreeSet<String>();
			System.out.println("noNeedEDirs.size()"+noNeedEDirs.size());
			System.out.println("needEDirs.size()"+needEDirs.size());
			
			for(int i=0;i<needEDirs.size();i++){
				boolean del=false;
				for(String _des:noNeedEDirs){
					if(_des.startsWith(needEDirs.get(i)+"/") ){
						del=true; 
						break;
					}
				}
				if(del)
					continue;
					System.out.println(i+":"+needEDirs.size());
				for(int k=i+1;k<needEDirs.size();k++){
					if(k>=needEDirs.size())
						break;
					boolean del2=false;
					for(String _des:noNeedEDirs){
						if(_des.startsWith(needEDirs.get(k)+"/")){
							del2=true; 
							break;
						}
					}
					if(del2)
						continue;
					if(needEDirs.get(k).startsWith(needEDirs.get(i)+"/")){
						needEDirs.remove(k);
						k--;
						if(i>k)
							i--;
					}
					if(needEDirs.get(i).startsWith(needEDirs.get(k)+"/")){
						needEDirs.remove(i);
						i--;
						if(k>i)
							k--;
					}
					if(i==-1)
						break;
				}
			}
			needEDirs.add(args[0]);
			eout.println("needed dirs --"+needEDirs);
			eout.println("no needed dirs --"+noNeedEDirs);
			eout.flush();
			sts.addAll(needEDirs);
			System.out.println("needEDirs.size()2"+needEDirs.size());
			TreeSet<String> noNeedParDir_= new TreeSet<String>();
			for(String _uu: noNeedEDirs ){
				recursiveAddParPath(args[0],_uu,noNeedParDir_);
			}
			System.out.println("noNeedEDirs.size()"+noNeedEDirs.size());
			System.out.println("noNeedParDir_.size()"+noNeedParDir_.size());
			TreeSet<String> noNeedParDir= new TreeSet<String>();
			noNeedParDir.addAll(noNeedParDir_);
			
			eout.println("===========needed dirs To be Preserved============\n");
			eout.println("mkdir targetdir");
			eout.flush();
			for(String _st:sts){
				
				
				String _subdir=_st.substring(args[0].length());
				if(noNeedParDir.contains(_st)){
					if(_subdir.length()>0)
						eout.println("mkdir -p \"targetdir"+_subdir+"\"");
					cpFileListFile.add(_st);
					noNeedParDir.remove(_st);
				}
				else{
					if(_subdir.length()>0 && _subdir.lastIndexOf("/")>0){
						
						eout.println("mkdir -p \"targetdir"+_subdir.substring(0,_subdir.lastIndexOf("/"))+"\"");
						eout.println("cp -r \""+_st+"\" \"targetdir"+_subdir+"\"");
					}else {
						eout.println("cp -r \""+_st+"\" \"targetdir\"");
						
					}
				}
				eout.flush();
				
				for(int i=0;i<noNeedEDirs.size();i++){
					String noneed=noNeedEDirs.get(i); 
					if(noneed.startsWith(_st+"/") &&  noneed.lastIndexOf("/") == _st.length()){
						eout.println("\techo \"---minus "+noneed+"\"");
						noNeedEDirs.remove(i);
						i--;
					}
				}
			}
			eout.flush();
			for(int i=0;i<noNeedEDirs.size();i++){
				String noneed=noNeedEDirs.get(i); 
				eout.println("echo \"-minus "+noneed+"\"");
			}
			eout.println("\n\n\n echo \"Please Check manually following files (some are omitted)");
			eout.println(" echo \"copying needed files from "+cpFileListFile+"\"\n");
			eout.flush();
		}
		
		
		
		
		

		
		TreeMap<Long,String> smp= new TreeMap<Long, String>();
		BufferedReader br1= new BufferedReader(new InputStreamReader(new FileInputStream(e+"dirs1.log")));
		String line="";
		int __k="=======SIZE=".length();
		long _len=0;
		boolean _cont=false;
		StringBuffer sb= new StringBuffer("");
		String pre="";
		long total=0;
		while((line=br1.readLine())!= null){
			if(line.startsWith("=======SIZE=")){
				if(sb.toString().length()>0){
					String tt=smp.get(_len);
					if(tt==null)
						smp.put(_len, pre+"\n"+sb.toString());
					else
						smp.put(_len, tt+sb.toString());
				}
				_len=Long.parseLong(line.substring(__k,line.indexOf("==",__k)));
				sb= new StringBuffer("");
				pre=line;
			}else if(line.trim().length()==0){
				if(sb.toString().length()>0){
					String tt=smp.get(_len);
					if(tt==null)
						smp.put(_len, pre+"\n"+sb.toString());
					else
						smp.put(_len, tt+sb.toString());
				}
			}
			else if(line.startsWith("meld")){
				total+=_len;
				sb.append(line+"\n");
			}
			
		}
		br1.close();
		
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(e+"dirs1.sort.log")));
		Set<Long> ss= smp.keySet();
		for(Long l:ss){
			bw.write(smp.get(l));
		}
		bw.write("\n\nTOTAL="+total);
		bw.close();

		AnalyzeFilesWithExistFile1.main(args);
		if(generateScriptFlag){
			ArrayList<String> allfls=new ArrayList<String>();
			Collection<List<String>> col= AnalyzeFilesWithExistFile1.efilemap.values();
			int len_=args[0].length();
			for(List<String> vals:col){
				for(String val:vals){
					String valParent=val.substring(0,val.lastIndexOf("/"));
					if(!AnalyzeFilesWithExistFile1.remFiles.contains(val) && cpFileListFile.contains(valParent))
						eout.println("cp \""+val+"\"  \"targetdir"+val.substring(len_)+"\"");
				}
				eout.flush();
			}
			
			ArrayList<String> allFies= new ArrayList<String>();
			
			
			eout.println("\n\n\n echo \"Or Copy All Files(None are omitted)");
			eout.println(" echo \"copying All files from "+cpFileListFile+"\"\n");
			eout.flush();
			for(String cpf:cpFileListFile){
				eout.println("cp \""+cpf+"\"/*  \"targetdir"+cpf.substring(len_)+"\"");
			}
		}

		eout.close();
		eoutrm.close();
		
	}
	
	static private String path(String file){
		int i=file.length();
		int _jj=file.lastIndexOf("_");
		return (String)dir_props.get(file.substring(1,_jj));
		
	}
	
	static private String epath(String file){
		int i=file.length();
		int _jj=file.lastIndexOf("_");
		return (String)edir_props.get(file.substring(1,_jj));
		
	}
	
	static void recursiveAddParPath(String root_path,String curr_path,TreeSet<String> paths){
		if(curr_path.length() > root_path.length() && curr_path.startsWith(root_path)){
			paths.add(root_path);
			int i=root_path.length();
			int i2=curr_path.length();
			while(i<i2){
				i=curr_path.indexOf("/",i+1);
				if(i<0)
					break;
				paths.add(curr_path.substring(0,i));
			}
			
		}
			
	}

	



	public static Properties loadProperties(String fileName) throws Exception{
		ByteArrayOutputStream bao=new ByteArrayOutputStream();
		FileInputStream fis=new FileInputStream(fileName);
		Crypto.getInstance().decrypt(fis, bao);
		byte[] barr=bao.toByteArray();
		ByteArrayInputStream bis= new ByteArrayInputStream(barr);
		Properties props= new Properties();
		props.loadFromXML(bis);
		bao.close();
		fis.close();
		return props;
	}
	public static String encrypt(String str){
		return Crypto.getInstance().encrypt(str);
	}
	public static String decrypt(String str){
		return Crypto.getInstance().decrypt(str);
	}

}
